package team.seekers.hula.teamwork.todo.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import team.seekers.hula.common.entity.result.ApiExceptionEnum;
import team.seekers.hula.common.entity.enums.WindTypeEnum;
import team.seekers.hula.common.entity.enums.todo.TodoStatusEnum;
import team.seekers.hula.common.entity.enums.todo.TodoTypeEnum;
import team.seekers.hula.common.entity.result.ApiException;
import team.seekers.hula.record.wind.service.WindService;
import team.seekers.hula.auth.service.MindUtils;
import team.seekers.hula.teamwork.team.team.entity.vo.TeamListVO;
import team.seekers.hula.teamwork.team.team.service.TeamService;
import team.seekers.hula.teamwork.teamTodo.entity.dao.TeamTodoDO;
import team.seekers.hula.teamwork.teamTodo.entity.dto.TeamTodoParticipantAddDTO;
import team.seekers.hula.teamwork.teamTodo.entity.dto.TeamTodoParticipantUpdateDTO;
import team.seekers.hula.teamwork.teamTodo.entity.vo.TeamTodoListVO;
import team.seekers.hula.teamwork.teamTodo.entity.vo.TeamTodoParticipantTodoInfoVO;
import team.seekers.hula.teamwork.teamTodo.entity.vo.TeamTodoTeamListVO;
import team.seekers.hula.teamwork.teamTodo.mapper.TeamTodoMapper;
import team.seekers.hula.teamwork.teamTodo.service.TeamTodoService;
import team.seekers.hula.teamwork.todo.entity.dao.TodoDO;
import team.seekers.hula.teamwork.todo.entity.dto.TodoMeAddPA;
import team.seekers.hula.teamwork.todo.entity.dto.TodoQuery;
import team.seekers.hula.teamwork.todo.entity.dto.TodoUpdatePA;
import team.seekers.hula.teamwork.todo.entity.vo.TodoListVO;
import team.seekers.hula.teamwork.todo.mapper.TodoMapper;
import team.seekers.hula.user.user.entity.vo.UserBasicInfoVO;
import team.seekers.hula.user.user.service.UserService;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.util.*;

/**
 * 一个混合待办（定位今日待办） 服务实现类
 *
 * @author yiming
 */
@Service
public class TodoService extends ServiceImpl<TodoMapper, TodoDO> {

    @Resource
    private TeamTodoMapper teamTodoMapper;

    @Resource
    private TeamService teamService;

    @Resource
    private TeamTodoService teamTodoService;

    @Resource
    private UserService userService;

    @Resource
    private WindService windService;

    private Date getToday() {
        LocalDate date = LocalDate.now();
        Date today = new Date(date.getYear(), date.getMonthValue(), date.getDayOfMonth());
        System.out.println(today.toString());
        return today;
    }

    /**
     * 新建个人待办
     */
    public void add(TodoMeAddPA todoMeAddPA) {
        TodoDO todoDO = new TodoDO();
        BeanUtils.copyProperties(todoMeAddPA, todoDO);

        todoDO.setUserId(MindUtils.getUserId())
                .setIsDelete(0)
                .setStatus(TodoStatusEnum.UNDO);
        String tagIdsString = String.join("&", todoMeAddPA.getTagIds());
        todoDO.setTags(tagIdsString);
        save(todoDO);

    }

    /**
     * 修改待办
     */
    public void update(TodoUpdatePA todoUpdatePA) {
        TodoDO todoDO = getById(todoUpdatePA.getId());
        BeanUtils.copyProperties(todoUpdatePA, todoDO);
        String tagIdsString = String.join("&", todoUpdatePA.getTagIds());
        todoDO.setTags(tagIdsString);
        updateById(todoDO);
    }

    /**
     * 完成待办
     */
    @Transactional(rollbackFor = Exception.class)
    public void finish(String id) {
        // 个人待办
        TodoDO todoDO = getById(id);
        if(todoDO == null){
            throw new ApiException(ApiExceptionEnum.COMMON_FAIL, "待办已经删除");
        }
        String teamTodoId = todoDO.getTeamTodoId(); // 团队待办id
        todoDO.setStatus(TodoStatusEnum.DONE);
        boolean b = updateById(todoDO);
        if(!b){
            throw new ApiException(ApiExceptionEnum.DB_FAIL);
        }

        // 团队待办
        if (!StringUtils.isBlank(teamTodoId)) {
            TeamTodoDO teamTodoDO = teamTodoMapper.selectById(teamTodoId);
            if(teamTodoDO == null){
                throw new ApiException(ApiExceptionEnum.COMMON_FAIL, "待办已经删除");
            }
            teamTodoDO.setFinishNumber(teamTodoDO.getFinishNumber() + 1);
            teamTodoMapper.updateById(teamTodoDO);

            windService.addWind(WindTypeEnum.FINISH_TODO_TEAM,id,2);

        }
    }

    /**
     * 恢复待办
     */
    @Transactional(rollbackFor = Exception.class)
    public void recover(String id) {
        TodoDO todoDO = getById(id);
        if(todoDO == null){
            throw new ApiException(ApiExceptionEnum.COMMON_FAIL, "待办已经删除");
        }

        //  黄老板代码真传（doge.jpg）（让我看看.jpg）
        /*if(!todoUpdatePA.getTagIds().isEmpty()){
            String tabs = "";
            List<String> tabIds = todoUpdatePA.getTagIds();
            for (String tabId : tabIds) {
                tabs = tabs +"&"+ tabId ;
            }
            String substring = tabs.substring(1);
            todo.setTags(substring);
        }*/

        todoDO.setStatus(TodoStatusEnum.UNDO);
        boolean b = updateById(todoDO);
        if(!b){
            throw new ApiException(ApiExceptionEnum.DB_FAIL);
        }
        String teamTodoId = todoDO.getTeamTodoId();
        // 团队待办
        if (!StringUtils.isBlank(teamTodoId)) {
            TeamTodoDO teamTodoDO = teamTodoMapper.selectById(teamTodoId);
            if(teamTodoDO == null){
                throw new ApiException(ApiExceptionEnum.COMMON_FAIL, "待办已经删除");
            }
            teamTodoDO.setFinishNumber(teamTodoDO.getFinishNumber() - 1);
            int i = teamTodoMapper.updateById(teamTodoDO);
            if(i == 0){
                throw new ApiException(ApiExceptionEnum.DB_FAIL);
            }

            windService.removeWind(WindTypeEnum.FINISH_TODO_TEAM,id);
        }
    }

    /**
     * 移入或移出今日待办
     */
    public void moveInOrOutToday(String id) {
        TodoDO todoDO = getById(id);
        todoDO.setIsToday(todoDO.getIsToday() == 1 ? 0 : 1);
        updateById(todoDO);
    }


    /**
     * 分页查询所有已完成待办
     */
    public List<TodoListVO> pageTodoFinished(long current, long limit) {
        Page<TodoDO> todoPage = new Page<>(current, limit);
        QueryWrapper<TodoDO> wrapper = new QueryWrapper<>();
        wrapper.eq("status", 1)
                .eq("user_id",MindUtils.getUserId())
                .orderByDesc("modified_date");
        this.page(todoPage, wrapper); // 调用方法时，底层封装，把分页所有数据都封装到todoPage对象里面
        List<TodoDO> records = todoPage.getRecords(); // 当前页记录
        if(records == null){
            throw new ApiException(ApiExceptionEnum.DB_FAIL);
        }
        // 封装已完成待办信息
        List<TodoListVO> todoListVOS = new ArrayList<>();

        int type;
        TodoListVO todoListVO;
        for (TodoDO record : records) {
            todoListVO = new TodoListVO();
            BeanUtils.copyProperties(record, todoListVO);

            // 待办类型： 0-个人 1-团体
            type = (record.getTeamTodoId() != null) ? 1 : 0;
            todoListVO.setType(type);
            todoListVOS.add(todoListVO);
        }
        return todoListVOS;
    }

    /**
     * 渲染个人待办
     * 根据userId和标签查询所有个人待办
     */
    public List<TodoListVO> todoList(TodoQuery todoQuery) {
        List<TodoListVO> todoListVOS = new ArrayList<>();
        QueryWrapper<TodoDO> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id", MindUtils.getUserId());
        wrapper.orderByAsc("gmt_modified");
        List<TodoDO> todoDOS = baseMapper.selectList(wrapper);
        if(todoDOS == null){
            throw new ApiException(ApiExceptionEnum.DB_FAIL);
        }

        // 根据tab删除不符合的选项
        for (int i = 0; i < todoDOS.size(); i++) {
            String[] tabIds = todoDOS.get(i).getTags().split("&");
            List<String> strings = Arrays.asList(tabIds);

            for (String tabId : todoQuery.getTagIds()) {
                if(!strings.contains(tabId)){
                    todoDOS.remove(i);
                    i--;
                    break;
                }
            }
        }
        // 封装个人待办信息
        TodoListVO todoListVO;
        int type;
        for (TodoDO todoDO : todoDOS) {
            todoListVO = new TodoListVO();
            BeanUtils.copyProperties(todoDO, todoListVO);

            String[] tags = todoDO.getTags().split("&");
            todoListVO.setTagIds(Arrays.asList(tags));

            type = (todoDO.getTeamTodoId() != null) ? 1 : 0;
            if(type == 1){
                String teamId = teamTodoService.getById(todoDO.getTeamTodoId()).getTeamId();
                String title = teamService.getById(teamId).getName();
                todoListVO.setTeamName(title);
            }
            todoListVO.setStatus(todoDO.getStatus().getType());
            todoListVOS.add(todoListVO.setType(type));
        }
        return todoListVOS;
    }

    /**
     * 渲染所有今日待办
     */
    public Map<String, Object> todayList(String userId) {
        List<TodoListVO> todoListVOS = new ArrayList<>();
        QueryWrapper<TodoDO> wrapper = new QueryWrapper<>();
        wrapper.eq("is_today",1)
                .eq("user_id", userId);
        List<TodoDO> todoDOS = baseMapper.selectList(wrapper);

        // 超时的待办
        List<TodoListVO> todoOverList = new ArrayList<>();

        // 已完成的待办
        List<TodoListVO> todoDownList = new ArrayList<>();

        for (TodoDO todoDO : todoDOS) {
            TodoListVO todoListVO = new TodoListVO();
            BeanUtils.copyProperties(todoDO, todoListVO);
            todoListVO.setIsToday(1);
            todoListVO.setStatus(todoDO.getStatus().getType());
            todoListVO.setType(todoDO.getType().getType());

            String[] tags = todoDO.getTags().split("&");
            todoListVO.setTagIds(Arrays.asList(tags));

            if(TodoTypeEnum.TEAM.equals(todoDO.getType()) ||TodoTypeEnum.TEAM_MONITOR.equals(todoDO.getType())){
                String teamId = teamTodoService.getById(todoDO.getTeamTodoId()).getTeamId();
                String title = teamService.getById(teamId).getName();
                todoListVO.setTeamName(title);
            }

            switch (todoDO.getStatus()){
                case UNDO:
                    todoListVOS.add(todoListVO);
                    break;
                case DONE:
                    todoDownList.add(todoListVO);
                case OVERDO:
                    todoOverList.add(todoListVO);
            }
        }

        Map<String, Object> map = new HashMap<>();
        map.put("todoList",todoListVOS);
        map.put("todoDownList",todoDownList);
        map.put("todoOverList",todoOverList);

        return map;
    }

    /**
     * 为负责人新增团队待办
     */
    @Transactional(rollbackFor = {RuntimeException.class})
    public void addTeamMonitorTodo(TeamTodoDO teamTodoDO, TeamTodoParticipantAddDTO monitor) {
        TodoDO todoDO = new TodoDO();
        todoDO.setUserId(monitor.getUserInfo().getId());
        todoDO.setGmtEnd(teamTodoDO.getGmtEnd());
        todoDO.setHulaCoin(monitor.getHulaCoin());
        todoDO.setTitle("负责团队待办");
        todoDO.setTeamTodoId(teamTodoDO.getId());
        todoDO.setTeamTodoTitle(teamTodoDO.getTitle());
        todoDO.setType(TodoTypeEnum.TEAM_MONITOR);
        save(todoDO);
    }

    /**
     * 批量为参与人新增团队待办
     */
    @Transactional(rollbackFor = {RuntimeException.class})
    public void addTeamParticipantTodos(List<TeamTodoParticipantAddDTO> participants) {
        ArrayList<TodoDO> todoDOS = new ArrayList<>();
        for (TeamTodoParticipantAddDTO participant : participants) {
            todoDOS.add(TodoDO.builder()
                    .userId(participant.getUserInfo().getId())
                    .type(TodoTypeEnum.TEAM)
                    .teamTodoId(participant.getTeamTodoId())
                    .title(participant.getTitle())
                    .teamTodoTitle(participant.getTeamTodoTitle())
                    .hulaCoin(participant.getHulaCoin())
                    .gmtEnd(participant.getGmtEnd())
                    .build()
            );
        }
        saveBatch(todoDOS);
    }

    /**
     * 为参与人新增团队待办
     */
    @Transactional(rollbackFor = {RuntimeException.class})
    public String addTeamParticipantTodo(TeamTodoParticipantAddDTO participant) {
        TodoDO todoDO = TodoDO.builder()
                .userId(participant.getUserInfo().getId())
                .type(TodoTypeEnum.TEAM)
                .teamTodoId(participant.getTeamTodoId())
                .title(participant.getTitle())
                .teamTodoTitle(participant.getTeamTodoTitle())
                .hulaCoin(participant.getHulaCoin())
                .gmtEnd(participant.getGmtEnd())
                .build();
        save(todoDO);
        return todoDO.getId();
    }

    /**
     * 修改队员团队待办
     */
    @Transactional(rollbackFor = {RuntimeException.class})
    public void updateTeamParticipantTodos(TeamTodoDO teamTodoDO) {
        List<TodoDO> todoDOList = lambdaQuery()
                .select(TodoDO::getId,TodoDO::getGmtEnd)
                .eq(TodoDO::getTeamTodoId, teamTodoDO.getId())
                .list();

        for (TodoDO todoDO : todoDOList) {
            todoDO.setTeamTodoTitle(teamTodoDO.getTitle());
            todoDO.setGmtEnd(todoDO.getGmtEnd().after(teamTodoDO.getGmtEnd()) ? teamTodoDO.getGmtEnd() : todoDO.getGmtEnd());
        }

        updateBatchById(todoDOList);
    }

    /**
     * 修改队员团队待办具体任务
     */
    @Transactional(rollbackFor = {RuntimeException.class})
    public void updateTeamParticipantTodo(TeamTodoParticipantUpdateDTO updateDTO) {
        LambdaUpdateChainWrapper<TodoDO> wrapper = lambdaUpdate()
                .eq(TodoDO::getId, updateDTO.getId());

        if(updateDTO.getHulaCoin() != null)
            wrapper.set(TodoDO::getHulaCoin,updateDTO.getHulaCoin());
        if(updateDTO.getUserInfo() != null && updateDTO.getUserInfo().getId() != null)
            wrapper.set(TodoDO::getUserId,updateDTO.getUserInfo().getId());
        if(updateDTO.getTitle() != null)
            wrapper.set(TodoDO::getTitle,updateDTO.getTitle());
        if(updateDTO.getGmtEnd() != null)
            wrapper.set(TodoDO::getGmtEnd,updateDTO.getGmtEnd());


        wrapper.update();
    }

    /**
     * 删除队员团队待办
     */
    @Transactional(rollbackFor = {RuntimeException.class})
    public void deleteTeam(String teamTodoId) {
        lambdaUpdate().eq(TodoDO::getTeamTodoId,teamTodoId).remove();
    }



    /**
     * 完成队员的团队待办
     */
    @Transactional(rollbackFor = {RuntimeException.class})
    public void finishTeam(String teamTodoId) {
        QueryWrapper<TodoDO> wrapper = new QueryWrapper<>();
        wrapper.eq("team_todo_id", teamTodoId);
        // 查询出每个队员的团队待办
        List<TodoDO> todoDOS = baseMapper.selectList(wrapper);
        if(todoDOS == null){
            throw new ApiException(ApiExceptionEnum.DB_FAIL);
        }
        // 依次更新
        for (TodoDO todoDO : todoDOS) {
            todoDO.setStatus(TodoStatusEnum.DONE);
            int i = baseMapper.updateById(todoDO);
            if(i == 0){
                throw new ApiException(ApiExceptionEnum.DB_FAIL);
            }
        }
    }

    /**
     * 检查是否是团队待办id
     */
    public boolean isTeamTodoId(String id) {
        TodoDO todoDO = getById(id);
        if(todoDO == null){
            throw new ApiException(ApiExceptionEnum.COMMON_FAIL, "待办已经删除");
        }
        return todoDO.getTeamTodoId() != null;
    }


    /**
     * 完成各待办总数的封装
     */
    public Map<String, Integer> countTodo(String userId) {
        Map<String, Integer> map = new HashMap<>();
        QueryWrapper<TodoDO> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id", userId);
        List<TodoDO> todoDOList = baseMapper.selectList(wrapper);
        if(todoDOList == null){
            throw new ApiException(ApiExceptionEnum.DB_FAIL);
        }

        int undone = 0;   // 待完成待办数目
        int done = 0;     // 已完成待办数目
        int overdo = 0;   // 超时待办数目
        int todayNum = 0;    // 今日待办数目
        TodoStatusEnum status; // 待办状态
        LocalDate today = LocalDate.now();
        for (TodoDO todoDO : todoDOList) {
            status = todoDO.getStatus();
            if (status == TodoStatusEnum.UNDO) {
                undone += 1;
            } else if (status == TodoStatusEnum.DONE) {
                done += 1;
            } else if (status == TodoStatusEnum.OVERDO) {
                overdo += 1;
            }
            if (todoDO.getIsToday() == 1) {
                todayNum += 1;
            }
        }
        map.put("undone", undone);
        map.put("done", done);
        map.put("overdo", overdo);
        map.put("today", todayNum);
        return map;
    }


    /**
     * 根据团队待办id删除个人团队待办
     */
    @Transactional(rollbackFor = {RuntimeException.class})
    public void removeByTeamTodoId(String teamTodoId) {
        lambdaUpdate().eq(TodoDO::getTeamTodoId,teamTodoId).remove();
    }

    /**
     * 根据团队待办id集合删除个人团队待办
     */
    @Transactional(rollbackFor = {RuntimeException.class})
    public void removeByTeamTodoIds(ArrayList<String> teamTodoIds) {
        lambdaUpdate().in(TodoDO::getTeamTodoId,teamTodoIds).remove();
    }

    /**
     * 渲染个人所有团队待办,分两层，上层是所有的团队，团队的VO中包含该团队所有未完成toto的list
     */
    public List<TeamTodoTeamListVO> teamTodoList(TodoQuery todoQuery) {
        List<TeamTodoTeamListVO> todoListVOS = new ArrayList<>();
        List<TeamListVO> teamListVOS = teamService.listMeIn();

        for (TeamListVO teamListVO : teamListVOS) {
            TeamTodoTeamListVO teamTodoTeamListVO = new TeamTodoTeamListVO();
            teamTodoTeamListVO.setTeamId(teamListVO.getId());
            teamTodoTeamListVO.setTeamTitle(teamListVO.getName());
            List<TodoListVO> listVOS = new ArrayList<>();
            List<TeamTodoListVO> teamTodoListVOS = teamTodoService.teamTodoList(teamListVO.getId());
            if(teamTodoListVOS == null){
                throw new ApiException(ApiExceptionEnum.DB_FAIL);
            }
            for (TeamTodoListVO teamTodoListVO : teamTodoListVOS) {
                QueryWrapper<TodoDO> wrapper = new QueryWrapper<>();
                wrapper.eq("team_todo_id", teamTodoListVO.getId());
                wrapper.eq("user_id",MindUtils.getUserId());
                wrapper.ne("type",0);
                List<TodoDO> list = list(wrapper);


                // 根据tab删除不符合的选项
                for (int i = 0; i < list.size(); i++) {
                    String[] tabIds = list.get(i).getTags().split("&");
                    List<String> strings = Arrays.asList(tabIds);

                    for (String tabId : todoQuery.getTagIds()) {
                        if(!strings.contains(tabId)){
                            list.remove(i);
                            i--;
                            break;
                        }
                    }
                }

                for (TodoDO todoDO : list) {
                    TodoListVO todoListVO = new TodoListVO();
                    BeanUtils.copyProperties(todoDO, todoListVO);
                    todoListVO.setStatus(todoDO.getStatus().getType());
                    int type = (todoDO.getTeamTodoId() != null) ? 1 : 0;
                    listVOS.add(todoListVO.setType(type));
                }
            }
            teamTodoTeamListVO.setTodoList(listVOS);
            todoListVOS.add(teamTodoTeamListVO);
        }
        return todoListVOS;
    }






    @Scheduled(cron = "0 0 0 * * ?")
    public void updateTodayTodo() {
        QueryWrapper<TodoDO> wrapper = new QueryWrapper<>();
        wrapper.eq("is_today",1);
        List<TodoDO> list = list(wrapper);
        for (TodoDO todoDO : list) {
            todoDO.setIsToday(0);
            updateById(todoDO);
        }
    }


    public TeamTodoParticipantTodoInfoVO getMonitorTodoInfo(String teamTodoId, String userId) {
        TodoDO todoDO = lambdaQuery()
                .eq(TodoDO::getTeamTodoId, teamTodoId)
                .eq(TodoDO::getUserId, userId)
                .eq(TodoDO::getType, TodoTypeEnum.TEAM_MONITOR.getType()).one();

        TeamTodoParticipantTodoInfoVO todoInfoVO = new TeamTodoParticipantTodoInfoVO();
        BeanUtils.copyProperties(todoDO,todoInfoVO);
        todoInfoVO.setUserInfo(userService.getBasicInfoVO(todoDO.getUserId()));
        return todoInfoVO;
    }

    public List<TeamTodoParticipantTodoInfoVO> getParticipantTodoInfoList(String teamTodoId) {
        List<TodoDO> todoDOList = lambdaQuery()
                .eq(TodoDO::getTeamTodoId, teamTodoId)
                .eq(TodoDO::getType, TodoTypeEnum.TEAM.getType()).list();

        ArrayList<String> userIds = new ArrayList<>();


        for (TodoDO todoDO : todoDOList) {
            userIds.add(todoDO.getUserId());
        }
        Map<String,UserBasicInfoVO> map =  userService.idsMapBasicInfoVOList(userIds);


        ArrayList<TeamTodoParticipantTodoInfoVO> todoInfoVOList = new ArrayList<>();
        for (TodoDO todoDO : todoDOList) {
            TeamTodoParticipantTodoInfoVO todoInfoVO = new TeamTodoParticipantTodoInfoVO();
            BeanUtils.copyProperties(todoDO,todoInfoVO);
            todoInfoVO.setUserInfo(map.get(todoDO.getUserId()));
            todoInfoVOList.add(todoInfoVO);
        }


        return todoInfoVOList;
    }
}
